/**
*  Copyright (c) 2011, Alex Theodoridis
*  All rights reserved.

*  Redistribution and use in source and binary forms, with 
*  or without modification, are permitted provided that the 
*  following conditions are met:
*  Redistributions of source code must retain the above 
*  copyright notice, this list of conditions and the following disclaimer.
*  Redistributions in binary form must reproduce the above 
*  copyright notice, this list of conditions and the following
*  disclaimer in the documentation and/or other materials 
*  provided with the distribution.

*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
*  AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
*  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
*  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
*  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
*  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
*  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
*  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
*  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE,
*  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
*/

#pragma once
#include <NeuralNetwork/Perceptron/NeuralLayer/NeuralLayer.h>

namespace nn {

    template<class Var>
    class InputLayer {
    private:
        std::map<unsigned int, Var> _inputs;

    public:

        InputLayer(unsigned int inputsNumber) throw (NNException) {
            if (inputsNumber == 0) {
                throw NNException("Wrong argument inputsNumber", __FILE__, __LINE__ );
            }

            for (unsigned int i = 0; i < inputsNumber; i++) {
                if (_inputs.insert(  std::make_pair(_inputs.size(), 0) ).second == false) {
                    throw NNException("Memory allocation error", __FILE__, __LINE__ );
                }
            }
        }

        bool calculateLayer(utils::SharedPtr<NeuralLayer<Var> >& nextLayer) {
            if (nextLayer == NULL) {
                return false;
            }

            typename std::map<unsigned int, Var>::iterator curInput;
            for (curInput = _inputs.begin(); curInput != _inputs.end(); curInput++) {
                nextLayer->setInput(curInput->first, curInput->second);
            }

            return true;
        }

        bool setValue(unsigned int id, const Var& value) {
            if (_inputs.find(id) == _inputs.end()) {
                return false;
            }

            _inputs[id] = value;
            return true;
        }

        unsigned int getInputsNumber(void) {
            return _inputs.size();
        }

        Var getInput(unsigned int inputId) throw (NNException) {
            if (_inputs.find(inputId) == _inputs.end()) {
                throw NNException("InputLayer::InputLayer : Wrong inputId");
            }

            return _inputs[inputId];
        }

        virtual ~InputLayer(void) {
        }
    };

}

